/*******************************************************************
 * File:         wimp.c
 * Purpose:      Acronyms translation
 * File purpose: Wimp (front-end) functions
 * Author:       Richard Butler & Gareth Duncan
 * Date:         21 Dec 2001
 ******************************************************************/

/*
    Acronyms - Translation of Internet and Computer-releated Acronyms
    Copyright  1996-1997-1998-1999-2000-2001, Richard Butler & Gareth Duncan

    Thanks are due to Gareth Dukes for the sprites used in this program and
    Gareth Duncan for letting me (Rich) develop this program further.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/

#include "acronyms.h"

int QUIT_FLAG;
extern int pass;

window_data win_array[2];
menu_data globmen, help_menu, options_menu, open_menu;
_kernel_swi_regs in, out;

//***************************************************************************
// WIMP
// Polling the WIMP
//***************************************************************************
int wimp(void)
{
  wimp_t task_handle; // Holds the programs task handle
  unsigned char pollblock[257];// A byte array  for our polling block
  int ibar_icon_handle; // A variable to store our iconbar icon handle
  int pollresult; // Holds the poll instruction that the wimp has sent us

  task_handle = wimp_initialise(310, PROJECT_NAME, NULL, NULL);

  initialise_text_files();

  if(QUIT_FLAG == 0)
  {
    ibar_icon_handle = create_iconbar_icon(0,-1, 1u << 1 | 1u << 3 | 1u << 4 | 3u << 12);

    wimp_open_template("<Acronyms$Dir>.Templates");
    load_template(PROJECT_NAME, &win_array[0], 0);
    load_template("Info", &win_array[1], 0);
    wimp_close_template();

    while (QUIT_FLAG == 0)
    {
      pollresult = wimp_poll(1, (wimp_block *)pollblock, NULL);

      switch (pollresult)
      {
        case 2: wimp_open_window((wimp_open *)pollblock); break;
        //case 3: closewindow(pollblock); break;
        case 3: in.r[1] = (int) pollblock;
                _kernel_swi(Wimp_CloseWindow, &in, &out); break;
        case 6: mouseclick(pollblock); break;
        case 8: key_press(pollblock); break;
        case 9: menuselection(pollblock); break;
        case 17: case 18: case 19: wimpmsg(pollresult, pollblock); break;
      }
    }
  }

  // Close down our program
  wimp_close_down(task_handle);

  return 0;
}

//***************************************************************************
// WIMPMSG
// Receiving a message from the WIMP
//***************************************************************************
void wimpmsg(int result, unsigned char pollblock[])
{
  //This variable holds the number of the message that we were sent
  unsigned long int message_action;

  // The next line takes bytes 16 to 19 of the polling block and forms them
  // into a word holding the message action number
  message_action = byte_to_word(pollblock, 16);

  switch (message_action)
  {
    case 0: QUIT_FLAG = 1; // A request for our program to quit
    break;
  }
}

//***************************************************************************
// PUT_ICON_TEXT
// Send a string to a icon
//***************************************************************************
void put_icon_text(char *text, unsigned long int w_h, unsigned long int i_h)
{
   char *text_pointer;

   text_pointer = get_ptr(w_h, i_h);
   strcpy(text_pointer, text);
   wimp_set_icon_state((wimp_w)w_h, i_h, 0, 0);
}

//***************************************************************************
// CREATE_ICONBAR_ICON
// Place a icon on the iconbar
//***************************************************************************
int create_iconbar_icon(int priority, unsigned long int whichside, unsigned long int iconflags)
{
   unsigned char icon_block[40];
   // We need to build up an icon information datablock
   word_to_byte(whichside, icon_block, 0);
   word_to_byte(0, icon_block, 4);
   word_to_byte(0, icon_block, 8);
   word_to_byte(68, icon_block, 12);
   word_to_byte(68, icon_block, 16);
   word_to_byte(iconflags, icon_block, 20);

   // Copy the icon name into the appropriate place
   strcpy((char *) &icon_block[24], PROJECT_NAME);
   in.r[0] = priority;
   in.r[1] = (int) icon_block;
   _kernel_swi(Wimp_CreateIcon, &in, &out);

   return out.r[0]; // Return the icon handle
}

//***************************************************************************
// LOAD_TEMPLATE
// Load in the templates
//***************************************************************************
int load_template(char *template_name, window_data *win_data, int call)
{
   int workspace_length = 0;
   int next_entry;

   // interrogate file to find out how much space we need
   in.r[1] = 0; // tell SWI to find sizes
   in.r[5] = (int) template_name; // pass name to SWI
   in.r[6] = call; // 0 for first call

   _kernel_swi(Wimp_LoadTemplate, &in, &out);
   win_data->buffer = calloc(out.r[1], sizeof(unsigned char));
   workspace_length = out.r[2]; // err on side of caution
   win_data->workspace = calloc(workspace_length, sizeof(unsigned char));
   win_data->win_name = calloc(strlen( (char *) out.r[5]) + 1, sizeof(char));
   strcpy(win_data->win_name, (char *) out.r[5]);

   // Now reload template from file into memory
   in.r[1] = (int) win_data->buffer;
   in.r[2] = (int) win_data->workspace;
   in.r[3] = (int) win_data->workspace + workspace_length;
   in.r[4] = -1;
   in.r[5] = (int) win_data->win_name;
   in.r[6] = call;

   _kernel_swi(Wimp_LoadTemplate, &in, &out);
   next_entry = out.r[6];

   // Create the window, store window handle
   in.r[1] = (int) win_data->buffer;
   _kernel_swi(Wimp_CreateWindow, &in, &out);
   win_data->win_handle = out.r[0];

   return next_entry; // in case of wildcarded searches
}

//***************************************************************************
// GET_PTR
// Interrogates an icon to determine the address where its data is stored
//***************************************************************************
char *get_ptr(unsigned long int winhdl, unsigned long int iconhdl)
{
   unsigned char temp_buffer[255];
   char *result;

   word_to_byte(winhdl, temp_buffer, 0);
   word_to_byte(iconhdl, temp_buffer, 4);

   in.r[1] = (int) temp_buffer;
   _kernel_swi(Wimp_GetIconState, &in, &out);

   result = (char *) byte_to_word(temp_buffer, 28);

   return result;
}

//***************************************************************************
// BUILD_MENU
// Creates a menu
//***************************************************************************
void build_menu(char *title, menu_data *menu_dat)
{
   strcpy(menu_dat->title, title);
   menu_dat->colours = 7u | 2u << 8 | 7u << 16 | 0u << 24;
   menu_dat->width = 172;
   menu_dat->height = 44;
   menu_dat->vert_gap = 0;
   menu_dat->next_menuelem = NULL;
   menu_dat->size = sizeof(menu_data);
}

//***************************************************************************
// ADD_TO_MENU
// Add a item to a menu
//***************************************************************************
void add_to_menu(char *text, long int menu_flags, long int submenu, long int icon_flags, menu_data *menu_dat)
{
menu_element *pointer;

if(strlen(text) > 11) return;
// Work our way to end of menu list
if(menu_dat->next_menuelem == NULL) {
   menu_dat->next_menuelem = calloc(1, sizeof(menu_element));
   menu_dat->size += sizeof(menu_element);
   pointer = menu_dat->next_menuelem;
}
else {
   pointer = menu_dat->next_menuelem;
   while (pointer->next_menuelem != 0) { pointer = pointer->next_menuelem; }
   pointer->next_menuelem = calloc(1, sizeof(menu_element));
   menu_dat->size += sizeof(menu_element);
   pointer = pointer->next_menuelem;
}
   // set up data
   strcpy(pointer->menu_text, text);
   pointer->flags = menu_flags;
   pointer->submenu = submenu;

   // Apply standard icon flags
   icon_flags = icon_flags | 7u << 24 | 0u << 28 | 1u << 0 | 1u << 5;
   pointer->menu_iconflags = icon_flags;
}

//***************************************************************************
// CREATE_MENU
// Display the menu
//***************************************************************************
void create_menu(menu_data *menu_dat)
{
   menu_element *pointer;
   int i;

   // Assign memory
   menu_dat->datablock = calloc(1, menu_dat->size);
   // Begin copying data
   strcpy((char *)menu_dat->datablock, menu_dat->title);
   word_to_byte(menu_dat->colours, menu_dat->datablock, 12);
   word_to_byte(menu_dat->width, menu_dat->datablock, 16);
   word_to_byte(menu_dat->height, menu_dat->datablock, 20);
   word_to_byte(menu_dat->vert_gap, menu_dat->datablock, 24);
   // end of header info
   i = 28;

   pointer = menu_dat->next_menuelem;

   while(pointer != NULL) {
      word_to_byte(pointer->flags, menu_dat->datablock, i);
      i += 4;
      word_to_byte(pointer->submenu, menu_dat->datablock, i);
      i += 4;
      word_to_byte(pointer->menu_iconflags, menu_dat->datablock, i);
      i += 4;
      strcpy((char *) &menu_dat->datablock[i], pointer->menu_text);
      i += 12;
      pointer = pointer->next_menuelem;
   }
}

//***************************************************************************
// MENUSELECTION
// What to do when a menu it clicked...
//***************************************************************************
void menuselection(unsigned char pollblock[])
{
  // If the selected item is in the Help submenu...
  if(byte_to_word(pollblock, 0) == 1)
  {
    //...and it is the Help entry
    if(byte_to_word(pollblock, 4) == 0)
    {
      // Open the Help file
      os_cli("Filer_Run AcronymsDocs:Help");
    }
    //...and it is the History entry
    if(byte_to_word(pollblock, 4) == 1)
    {
      // Open the History file
      os_cli("Filer_Run AcronymsDocs:History");
    }
    //...and it is the Additional entry
    if(byte_to_word(pollblock, 4) == 2)
    {
      // Open the Additional file
      os_cli("Filer_Run AcronymsDocs:Additional");
    }
    //...and it is the Additional entry
    if(byte_to_word(pollblock, 4) == 3)
    {
      // Open the GPL file
      os_cli("Filer_Run AcronymsDocs:GPL");
    }
  }
  // If the selected item is in the Options submenu...
  if(byte_to_word(pollblock, 0) == 2)
  {
    // ...and it is in the OpenFiles submenu...
    if(byte_to_word(pollblock, 4) == 0)
    {
      //...and it is the Acronyms entry
      if(byte_to_word(pollblock, 8) == 0)
      {
        // Open the Acronyms file
        os_cli("Filer_Run AcronymsData:Acronyms");
      }
      //...and it is the Emoticons entry
      if(byte_to_word(pollblock, 8) == 1)
      {
        // Open the Emoticons file
        os_cli("Filer_Run AcronymsData:Computers");
      }
      //...and it is the Computers entry
      if(byte_to_word(pollblock, 8) == 2)
      {
        // Open the Computers file
        os_cli("Filer_Run AcronymsData:Emoticons");
      }
    }
    //...and it is the ScanFiles entry
    if(byte_to_word(pollblock, 4) == 1)
    {
      // Go to the function initialise_text_files
      initialise_text_files();
    }
  }

  // If the selected item is the quit option
  if(byte_to_word(pollblock, 0) == 3)
  {
   // Quit the program
   QUIT_FLAG = 1;
  }

  wimp_create_menu((wimp_menu *)globmen.datablock, (int)byte_to_word(pollblock, 0) - 64, (44*5)+96);
}

//***************************************************************************
// MOUSECLICK
// See's what the mouse presses
//***************************************************************************
void mouseclick(unsigned char pollblock[])
{
  char *text_pointer; // A pointer to the icons text

  int click; // Holds the mouse button that was click e.g. Select, Menu etc..
  unsigned char temp_buffer[255];

  // Determine which button was pressed
  click = (int) byte_to_word(pollblock, 8);

   // If the 'Select' or 'Adjust' button was clicked...
   if((click == 4) || (click == 1))
   {
     // ...on the icon bar then re-open main window and return
     if(byte_to_word(pollblock, 12) == -2)
     {
       word_to_byte(win_array[0].win_handle, temp_buffer, 0);
       wimp_get_window_info((wimp_window_info *)temp_buffer);
       wimp_open_window((wimp_open *)temp_buffer);
       // Get icon 1's text
       text_pointer=get_ptr(win_array[0].win_handle, 1);
       // Add a null character to the end of the string
       for(pass = 0; pass <= 19; pass++)
       {
         if(text_pointer[pass] < 32)
         {
           text_pointer[pass] = '\0';
           break;
         }
       }
       // Give the window the input focus
       wimp_set_caret_position((wimp_w)win_array[0].win_handle, 1, NULL, NULL, -1, (int) strlen(text_pointer));
       return;
     }
   }

   // If 'Menu' has been clicked on the icon bar icon...
     if((byte_to_word(pollblock, 12) == -2) && (click == 2))
   {

  build_menu("Help", &help_menu);
  add_to_menu("Help", 0, -1, 0, &help_menu);
  add_to_menu("History", 0, -1, 0, &help_menu);
  add_to_menu("Additional", 0, -1, 0, &help_menu);
  add_to_menu("GPL", 1u << 7, -1, 0, &help_menu);
  create_menu(&help_menu);

  build_menu("Open...", &open_menu);
  add_to_menu("Acronyms", 0, -1, 0, &open_menu);
  add_to_menu("Computers", 0, -1, 0, &open_menu);
  add_to_menu("Emoticons", 1u << 7, -1, 0, &open_menu);
  create_menu(&open_menu);

  build_menu("Options", &options_menu);
  add_to_menu("Open...", 0, (int) open_menu.datablock, 0, &options_menu);
  add_to_menu("Update", 1u << 7, -1, 0, &options_menu);
  create_menu(&options_menu);

  build_menu("Acronyms", &globmen);
  add_to_menu("Info", 1u << 1, win_array[1].win_handle, 0, &globmen);
  add_to_menu("Help", 0, (int) help_menu.datablock, 0, &globmen);
  add_to_menu("Options", 1u << 1, (int) options_menu.datablock, 0, &globmen);
  add_to_menu("Quit", 1u << 7, -1, 0, &globmen);
  create_menu(&globmen);

 wimp_create_menu((wimp_menu *)globmen.datablock, (int)byte_to_word(pollblock, 0) - 64, (44*5)+96);

 put_icon_text(VERSION, win_array[1].win_handle, 7);
   }
}

//***************************************************************************
// KEY_PRESS
// See's keys pressed with the keyboard
//***************************************************************************
void key_press(unsigned char pollblock[])
{
  int key; // Holds the key that was pressed

  key=byte_to_word(pollblock, 24); // Find out which key was pressed

  switch (key)
  {
    // If the key is F12 tell the wimp to process it
    case 460: wimp_process_key(key);
    break;
    // If the key is return go to the function check_acronym
    case 13: check_acronym(); // Call the function check_acronym
    break;
  }

}

//***************************************************************************
// WORD_TO_BYTE
// Handy function to convert word to byte
//***************************************************************************
void word_to_byte(unsigned long int input, unsigned char block[], int index)
{
   unsigned long int mask = 255;

   block[index++] = (char) (input & mask);
   mask <<= 8;
   block[index++] = (char) ((input & mask) >> 8);
   mask <<= 8;
   block[index++] = (char) ((input & mask) >> 16);
   mask <<= 8;
   block[index++] = (char) ((input & mask) >> 24);
}

//***************************************************************************
// BYTE_TO_WORD
// Handy function to convert byte to word
//***************************************************************************
unsigned long int byte_to_word(unsigned char block[], int index)
{
   unsigned long int result = 0;
   int loop;

   index += 3;
   result = block[index--];
   for(loop = 0; loop < 3; loop++) {
      result = result << 8;
      result += block[index--];
   }

   return result;
}
